package top.infopub.mgr.sys.service.impl;


import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import javax.annotation.PostConstruct;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import top.infopub.concurrent.ExecutorManager;
import top.infopub.generic.GenericDao;
import top.infopub.generic.GenericServiceImpl;
import top.infopub.mgr.sys.dao.CityDao;
import top.infopub.mgr.sys.domain.CityDomain;
import top.infopub.mgr.sys.domain.CountryDomain;
import top.infopub.mgr.sys.domain.LocationAreaDomain;
import top.infopub.mgr.sys.domain.ProvinceDomain;
import top.infopub.mgr.sys.service.CityService;
import top.infopub.mgr.sys.service.LocationAreaDataService;
import top.infopub.model.sys.Area;
import top.infopub.model.sys.City;
import top.infopub.model.sys.Province;
import top.infopub.zookeeper.confclient.listener.ConfigurationListener;


@Service("areaLocationService")
public class CityServiceImpl extends GenericServiceImpl<City, String> implements CityService, LocationAreaDataService, ConfigurationListener {

    @Autowired
    private CityDao cityDao;

    @Override
    public GenericDao<City, String> getDao() {
        return cityDao;
    }

    private Map<String, LocationAreaDomain> cache_areaId_fullinfo = null;

    private Map<String, ProvinceDomain> cache_proJp_profullinfo = null;

    private Map<String, CityDomain> cache_proJp_cityfullinfo = null;

    private CountryDomain countrydomains = null;

    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    @PostConstruct
    public void loadFullInfos() {
        ExecutorManager.getInstance().execute(new Runnable() {
            @Override
            public void run() {
                // 查询所有信息 （含：国家-省份-城市-区县）
                List<LocationAreaDomain> locaCitys = cityDao.selectCityFullInfos();
                try {
                    lock.writeLock().lock();
                    cache_areaId_fullinfo = new HashMap<String, LocationAreaDomain>();
                    cache_proJp_profullinfo = new HashMap<String, ProvinceDomain>();
                    cache_proJp_cityfullinfo = new HashMap<String, CityDomain>();
                    countrydomains = null;
                    for (LocationAreaDomain locaCity : locaCitys) {
                        LocationAreaDomain lad = cache_areaId_fullinfo.get(locaCity.getAreaId());
                        if (lad == null) {
                            cache_areaId_fullinfo.put(locaCity.getAreaId(), locaCity);
                        }
                        if (countrydomains == null) {
                            countrydomains = new CountryDomain();
                            countrydomains.setSjpname(locaCity.getCjp());
                            countrydomains.setSname(locaCity.getCname());
                            countrydomains.setSpyname(locaCity.getCpn());
                        }
                        countrydomains.addProvince(new Province(locaCity.getProviceId(),
                            locaCity.getPsort(), null, locaCity.getPjp(), locaCity.getPname(),
                            locaCity.getPpn()));

                        ProvinceDomain _proDomain = cache_proJp_profullinfo.get(locaCity.getProviceId());
                        if (_proDomain == null) {
                            _proDomain = new ProvinceDomain();
                            _proDomain.setSjpname(locaCity.getPjp());
                            _proDomain.setSname(locaCity.getPname());
                            _proDomain.setSpyname(locaCity.getPpn());
                            _proDomain.setId(locaCity.getProviceId());
                            cache_proJp_profullinfo.put(locaCity.getProviceId(), _proDomain);
                        }
                        _proDomain.addCity(new City(locaCity.getCityId(), null,
                            locaCity.getCispc(), locaCity.getCsort(), locaCity.getCacode(),
                            locaCity.getCjp(), locaCity.getCname(), locaCity.getProviceId(),
                            locaCity.getCpn()));

                        CityDomain _cityDomain = cache_proJp_cityfullinfo.get(locaCity.getCityId());
                        if (_cityDomain == null) {
                            _cityDomain = new CityDomain();
                            _cityDomain.setSname(locaCity.getCname());
                            _cityDomain.setId(locaCity.getCityId());
                            cache_proJp_cityfullinfo.put(locaCity.getCityId(), _cityDomain);
                        }
                        _cityDomain.addArea(new Area(locaCity.getAreaId(), locaCity.getAsort(),
                            locaCity.getAname(), locaCity.getCityId()));
                    }
                }
                finally {
                    lock.writeLock().unlock();
                }
            }
        });
    }

    /**
     * 根据区县ID查询相关信息包括 国家、省份、城市、区县信息
     */
    @Override
    public LocationAreaDomain selectLocationDataByAreaId(String areaId) {
        if (StringUtils.isEmpty(areaId) || cache_areaId_fullinfo == null) {
            return null;
        }
        try {
            lock.readLock().lock();
            LocationAreaDomain loa = cache_areaId_fullinfo.get(areaId);
            if (loa == null) {
                return null;
            }
            LocationAreaDomain _dest = new LocationAreaDomain();
            try {
                BeanUtils.copyProperties(_dest, loa);
                return _dest;
            }
            catch (Exception e) {
                return null;
            }
        }
        finally {
            lock.readLock().unlock();
        }
    }

    @Override
    public Set<Province> selectProvincesAndsort() {
        try {
            lock.readLock().lock();
            if (countrydomains != null) {
                return countrydomains.getListPros();
            }
        }
        finally {
            lock.readLock().unlock();
        }
        return null;
    }

    @Override
    public Set<City> selectCitysByProvIdAndSort(String proID) {
        if (StringUtils.isEmpty(proID) || cache_proJp_profullinfo == null) {
            return null;
        }
        try {
            lock.readLock().lock();
            ProvinceDomain loa = cache_proJp_profullinfo.get(proID);
            if (loa == null) {
                return null;
            }
            return loa.getListCitys();
        }
        finally {
            lock.readLock().unlock();
        }
    }

    @Override
    public Set<Area> selectAreasByCityIdAndSort(String cityID) {
        if (StringUtils.isEmpty(cityID) || cache_proJp_cityfullinfo == null) {
            return null;
        }
        try {
            lock.readLock().lock();
            CityDomain loa = cache_proJp_cityfullinfo.get(cityID);
            if (loa == null) {
                return null;
            }
            return loa.getListAreas();
        }
        finally {
            lock.readLock().unlock();
        }
    }

    @Override
    public String selectProvinceNameById(String proID) {
        if (StringUtils.isEmpty(proID) || cache_proJp_profullinfo == null) {
            return null;
        }
        try {
            lock.readLock().lock();
            ProvinceDomain loa = cache_proJp_profullinfo.get(proID);
            if (loa == null) {
                return null;
            }
            return loa.getSname();
        }
        finally {
            lock.readLock().unlock();
        }
    }

    @Override
    public String selectCityNameById(String cityID) {
        if (StringUtils.isEmpty(cityID) || cache_proJp_cityfullinfo == null) {
            return null;
        }
        try {
            lock.readLock().lock();
            CityDomain loa = cache_proJp_cityfullinfo.get(cityID);
            if (loa == null) {
                return null;
            }
            return loa.getSname();
        }
        finally {
            lock.readLock().unlock();
        }
    }

    @Override
    public String selectAreaNameById(String areaID) {
        if (StringUtils.isEmpty(areaID) || cache_areaId_fullinfo == null) {
            return null;
        }
        try {
            lock.readLock().lock();
            LocationAreaDomain loa = cache_areaId_fullinfo.get(areaID);
            if (loa == null) {
                return null;
            }
            return loa.getAname();
        }
        finally {
            lock.readLock().unlock();
        }
    }

    @Override
    public List<City> selectByProName(String proName) {
        return cityDao.selectByProName(proName);
    }

    @Override
    public City selectByName(String sname) {
        return cityDao.selectByName(sname);
    }

    @Override
    public void configurationChangedNotice(String keyName, String value) {
        if (ZK_NAME.equalsIgnoreCase(keyName)) {
            loadFullInfos();
        }
    }

}